// Author: Domien Nowicki

#include <math.h>
#include "MapWidget.h"

const qreal MapWidget::CENTERSCALE = 0.6;

MapWidget::MapWidget(QWidget *parent): QGraphicsView(parent), docenter(true), focusCell(0)
{
	SetupWidget();
	DefaultResize();
}

MapWidget::~MapWidget()
{
}

void MapWidget::SetupWidget()
{
	QGraphicsScene *scene = new QGraphicsScene(this);

	scene->setItemIndexMethod(QGraphicsScene::NoIndex);
	setScene(scene);
	setCacheMode(CacheBackground);
	setRenderHint(QPainter::Antialiasing);
	setTransformationAnchor(AnchorUnderMouse);
	setResizeAnchor(AnchorViewCenter);

	docenter = true;

	Center();
}

void MapWidget::SetCursor(const QCursor& cursor)
{
	// Set cursor on each graphicsitem
	QList<QGraphicsItem*>& list = items();
	for(int i=0; i < list.size(); ++i) 
	{
		QGraphicsItem *item = list.at(i);

		item->setCursor(cursor);
	}
}

void MapWidget::Resize(unsigned int newColumnCount, unsigned int newRowCount)
{
	Map::Resize(newColumnCount, newRowCount);

	Center();
}

CellWidget& MapWidget::GetCellWidget(unsigned int column, unsigned int row)
{
	CellWidget *cell = (CellWidget*)&GetCell(column, row);

	return *cell;
}

const CellWidget& MapWidget::GetCellWidget(unsigned int column, unsigned int row) const
{
	const CellWidget *cell = (const CellWidget*)&GetCell(column, row);

	return *cell;
}

void MapWidget::SetTextureCell(unsigned int column, unsigned int row, Cell::Side side, unsigned int tindex, const Pixel& userColor)
{
	Map::SetTextureCell(column, row, side, tindex, userColor);

	update();
}

// Tell listeners that a cell was clicked
void MapWidget::slotCellClicked(CellWidget* cell)
{
	emit clickedCell(cell->GetMapX(), cell->GetMapY());

}

// Tell listeners that a cellside was clicked
void MapWidget::slotCellSideClicked(CellWidget* cell, Cell::Side side)
{
	emit clickedCellSide(cell->GetMapX(), cell->GetMapY(), side);
}

void MapWidget::Center()
{
	// Center the scene rectangle
	setSceneRect(boundingRect());
	// Fit the scene rect in the widget window
	fitInView(boundingRect(), Qt::KeepAspectRatio);
}

void MapWidget::resizeEvent(QResizeEvent* e)
{
	// Update the scene rectangle
	setSceneRect( boundingRect() );

	if (docenter)
	{
		docenter = false;
		Center();
	}
}

Cell* MapWidget::NewCell(const Cell* copy, unsigned int column, unsigned int row)
{
	CellWidget *cellWidget;

	// A cellwidget adds itself automatically to the scene

	if (copy)
	{
		cellWidget = new CellWidget(scene(), *copy);
	}
	else
	{
		cellWidget = new CellWidget(scene(), column, row);
	}


	QObject::connect(cellWidget, SIGNAL(clicked(CellWidget*)), this, SLOT(slotCellClicked(CellWidget*)));
	QObject::connect(cellWidget, SIGNAL(clickedSide(CellWidget*, Cell::Side)), this, SLOT(slotCellSideClicked(CellWidget*, Cell::Side)));

	return cellWidget;
}


void MapWidget::wheelEvent(QWheelEvent *e)
{
	// Scale the graphics view
    scaleView(pow((double)2, e->delta() / 240.0));
}

void MapWidget::SetWallCell(unsigned int column, unsigned int row)
{
	Map::SetWallCell(column, row);

	update();
}

void MapWidget::SetEmptyCell(unsigned int column, unsigned int row)
{
	Map::SetEmptyCell(column, row);

	update();
}

void MapWidget::keyPressEvent(QKeyEvent *e)
 {
	 // Catch '+' and '-' keypresses to scale the map
     switch (e->key()) 
	 {
		 case Qt::Key_Plus:
			 //scale(1.2,1.2);
			 scaleView(1.2);
			 break;
		 case Qt::Key_Minus:
			 scaleView(1 / 1.2);
			 break;
	     default:
		     QGraphicsView::keyPressEvent(e);
     }
 }


void MapWidget::scaleView(qreal scaleFactor)
{
	// Scale the view matrix
	qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
	// Make sure its not going to be too large or too small
	if (factor < 0.07 || factor > 100)
		return;

	// Now do the scale
	scale(scaleFactor, scaleFactor);
}

QRectF MapWidget::boundingRect() const
{
	// Return the bounding rectangle of the map
	int xmin = 0;
	int xmax = GetColumnCount() * CELLSIZE;
	int ymin = 0;
	int ymax = GetRowCount() * CELLSIZE;


	return QRectF(xmin, ymin, (xmax-xmin), (ymax-ymin));
}

unsigned int MapWidget::GetCellWidgetSize() const
{
	return CELLSIZE;
}

